package 进阶阶段;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class demo21IO流_字节流 {
    public static void main(String[] args) throws Exception {
        //按照数据的流向分为：输入流和输出流。
        //输入流：把数据从`其他设备`上读取到`内存`中的流。 //功能,读数据
        //输出流：把数据从`内存` 中写出到`其他设备`上的流。//功能,把数据写到其他地方

        //按照数据的类型分为：字节流和字符流。
        //字节流：以字节为单位，读写数据的流。
        //字符流：以字符为单位，读写数据的流。//字符流=字节流+码表

        //字节输入流：InputStream
        //字节输出流：OutputStream
        //字符输入流：Reader
        //字符输出流：Writer
            //一般情况下,看到类以stream结尾是字节流,以er结尾的是字符流

        System.out.println("------------------------------------------");
        System.out.println("字节输出流：OutputStream");

        //字节输出流：OutputStream
            //close()：关闭此输出流,并释放与此流相关联的,任何系统资源。内置缓冲区刷新
            //flush()：刷新此输出流,并强制任何缓冲的输出字节被写出。
            //write(byte[] b)：将b.length字节从指定的字节数组写入此输出流。
            //write(byte[] b, int off, int len)：从指定的字节数组写入len字节，从偏移量 off开始输出到此输出流。
            //write(int b)：将指定的字节写到输出流。97,码表翻译a,打开文件是a

        //OutputStream的子类
        //FileOutputStream类：是文件输出流，把数据写出到文件中。
            //FileOutputStream(File file)：创建文件输出流,以写入由指定的 File对象表示的文件。
            //FileOutputStream(String name)：创建文件输出流,以指定的名称写入文件。

        // 使用File对象创建流对象
        File file = new File("a.txt");
        FileOutputStream fos = new FileOutputStream(file);//存在a.txt文件，会清空这个文件的数据
//        FileOutputStream fos = new FileOutputStream(file , true);//加‘, true’表示文件中的数据不会被清空

        //当你创建一个输出流对象写数据到文件中时，必须传入一个文件路径。输出流的构造方法，如果没有这个文件，会创建该文件。如果有这
        //个文件，会清空这个文件的数据(不想清空,在构造方法()里面加个逗号和true表示追加内容,不清空原来的数据)

        // 使用文件名称创建流对象
        FileOutputStream fos1 = new FileOutputStream("b.txt");

        //write(int b)方法：每次可以写出一个字节数据

        fos.write(97); // 写出第1个字节
        fos1.write(97); // 写出第1个字节

        byte[]  arr = {97 , 98 , 99 , 100};
        fos.write(arr);//写出多个字节

        fos.write(arr , 0 , 1);//写出这个数组下标从0开始，1个字节

//        fos.write("\r\n".getBytes());//写出换行
        //回车符`\r`和换行符`\n`：
            //回车符：回到一行的开头（return）。
            //换行符：下一行（newline）。
        //系统中的换行：
            //Windows系统里，每行结尾是 `回车+换行` ，即`\r\n`；
            //Unix系统里，每行结尾只有 `换行` ，即`\n`；
            //Mac系统里，每行结尾是 `回车` ，即`\r`。

        byte[]  arr1 = "我爱你".getBytes();//字符串变成数组
        fos.write(arr1);

        fos.write(arr1 , 0 , 6);//uft-8码表一个中文由3个字节组成，英文1个字节，结果是'我爱'
//        fos.write(arr1 , 0 , 4);//4位无法构成中文，导致‘爱’乱码

        // 关闭资源
        fos.close();
        fos1.close();



        System.out.println("------------------------------------------");
        System.out.println("字节输入流InputStream");

        //字节输入流InputStream
        //InputStream：抽象类是表示字节输入流的所有类的超类，可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。
            //close()：关闭此输入流,并释放与此流相关联的任何系统资源。
            //read()：从输入流读取数据的下一个字节。
            //read(byte[] b)：从输入流中读取一些字节数，并将它们存储到字节数组b中。

        //InputStream的子类
        //FileInputStream类：是文件输入流，用来读取文件的。
            //FileInputStream(File file)：通过打开与实际文件的连接来创建一个FileInputStream，该文件由文件系统中的 File对象 file命名。
            //FileInputStream(String name)：通过打开与实际文件的连接来创建一个FileInputStream，该文件由文件系统中的路径名 name命名。
        //当创建一个输入流对象时，必须传入一个文件路径。该路径下，如果没有该文件,会抛出`FileNotFoundException`

        // 使用File对象创建流对象
        File file1 = new File("b.txt");
        FileInputStream fos2 = new FileInputStream(file1);

        // 使用文件名称创建流对象
        FileInputStream fos3 = new FileInputStream("a.txt");

        int read = fos2.read();
//        System.out.println(read);//97
        System.out.println((char) read);//a

        int read1 = fos2.read();
        System.out.println(read1);//读取到末尾,返回-1

//        System.out.println("循环改进读取方式-多个字节");
//        //循环改进读取方式-单个字节
//        int ReadByte;
//        // 循环读取
//        while ((ReadByte = fos3.read())!=-1) {
//            System.out.println(ReadByte);//一次只能读取一个字节，不能读取中文，因为中文是由3个字节组成
//        }

        System.out.println("循环改进读取方式-多个字节");
        //循环改进读取方式-多个字节
        int ReadBytes;
        // 定义字节数组，作为装字节数据的容器
        byte[] b = new byte[3];
        // 循环读取
        while ((ReadBytes= fos3.read(b))!=-1) {
            // 每次读取后,把数组的有效字节部分，变成字符串打印
            System.out.println(new String(b , 0 , ReadBytes));//每次读取的有效字节个数
        }

        // 关闭资源
        fos2.close();
        fos3.close();



    }
}
